Imports System
Imports SlimDX
Imports SlimDX.Direct3D9
Public Class PitchedCamera
#Region "Structures"
    Enum MoveDirection As Integer
        Left = 1
        Right = 2
        Forward = 4
        Backward = 8
        Up = 16
        Down = 32
    End Enum
#End Region
#Region "Declarations"
    Friend Speed As Single = 5.0F
    Friend Pitched As Boolean = True
    Friend Position, Angle As Vector3
    Friend Update As Boolean = False
#End Region

#Region "Loading"
    Public Sub New()
        Position = New Vector3
        Angle = New Vector3
    End Sub
#End Region
#Region "Interface"
    Public Sub CycleSpeed()
        Select Case Speed
            Case 1.0F
                Speed = 5.0F
            Case 5.0F
                Speed = 20.0F
            Case 20.0F
                Speed = 40.0F
            Case 40.0F
                Speed = 80.0F
            Case 80.0F
                Speed = 160.0F
            Case 160.0F
                Speed = 320.0F
            Case 320.0F
                Speed = 640.0F
            Case 640.0F
                Speed = 1.0F
            Case Else
                Speed = 1.0F
        End Select
    End Sub
#End Region
#Region "Positioning"
    Function vDistance(ByVal v As Vector3) As Double
        Return Math.Sqrt((v.X - Position.X) * (v.X - Position.X) + (v.Y - Position.Y) * (v.Y - Position.Y) + (v.Z - Position.Z) * (v.Z - Position.Z))
    End Function
    Public Sub Move(ByVal Direction As MoveDirection, Optional ByVal Constant As Single = 0.04F)
        Select Case Direction
            Case MoveDirection.Forward
                Position.X += (Speed * Constant) * Angle.X
                Position.Y += (Speed * Constant) * Angle.Y
                If Pitched Then Position.Z += (Speed * Constant) * Angle.Z
            Case MoveDirection.Backward
                Position.X -= (Speed * Constant) * Angle.X
                Position.Y -= (Speed * Constant) * Angle.Y
                If Pitched Then Position.Z -= (Speed * Constant) * Angle.Z
            Case MoveDirection.Right
                Position.X += (Speed * Constant) * Angle.Y
                Position.Y -= (Speed * Constant) * Angle.X
            Case MoveDirection.Left
                Position.X -= (Speed * Constant) * Angle.Y
                Position.Y += (Speed * Constant) * Angle.X
            Case MoveDirection.Up
                Position.Z += (Speed * Constant) '/ 2.0F
            Case MoveDirection.Down
                Position.Z -= (Speed * Constant) '/ 2.0F
        End Select
        Update = True
    End Sub
    Public Sub Look(ByRef ScreenVector As Vector3)
        Angle.X = ScreenVector.X
        Angle.Y = ScreenVector.Y
        Angle.Z = ScreenVector.Z - (Math.PI / 4.0)
    End Sub
    Public ReadOnly Property View() As Matrix
        Get
            Return Matrix.LookAtRH(Position, New Vector3(Position.X + Angle.X, Position.Y + Angle.Y, Position.Z + Angle.Z), New Vector3(0.0F, 0.0F, 1.0F))
        End Get
    End Property

    Public ReadOnly Property World() As Matrix
        Get
            Return Matrix.Identity
        End Get
    End Property
    Public ReadOnly Property Projection() As Matrix
        Get
            Return Matrix.PerspectiveFovRH(CSng(Math.PI) / 4.0F, xDevice.Viewport.Width / xDevice.Viewport.Height, 0.1F, 1000000.0F)
        End Get
    End Property
#End Region

#Region "Translating By Time"
    'Current
    Dim currentPosition As Vector3
    Dim currentRotation As Vector3
    Dim CurrentVector As Integer = 0

    'All
    Public Positions() As Vector3
    Public Rotations() As Vector3
    Public Indices() As Integer = {0, 1, 2, 3}

    'Interpolation Variables
    Public Interpolate As Boolean
    Dim Interpolator As Single = 0

    Public Sub SetPosition(ByVal pos() As Vector3, ByVal rot() As Vector3)
        If pos.Length > 0 Then
            Positions = pos
            Rotations = rot
        End If
    End Sub
    Public Sub UpdateCamera()
        currentPosition = Vector3.CatmullRom(Positions(Indices(0)), Positions(Indices(1)), Positions(Indices(2)), Positions(Indices(3)), Interpolator)
        currentRotation = Vector3.CatmullRom(Rotations(Indices(0)), Rotations(Indices(1)), Rotations(Indices(2)), Rotations(Indices(3)), Interpolator)

        Interpolator += 0.01
        If Interpolator >= 1 Then
            If CurrentVector < Positions.Length - 1 Then
                CurrentVector += 1
            Else
                CurrentVector = 0
            End If
            For x As Integer = 0 To 3
                If (CurrentVector + x) < (Positions.Length - 1) Then
                    Indices(x) = CurrentVector + x
                Else
                    Indices(x) = (CurrentVector + x) - (Position.Length - 1)
                End If
            Next
            Interpolator = 0
        End If
    End Sub
    Public ReadOnly Property InterpolatedView2() As Matrix
        Get
            Return Matrix.Multiply(Matrix.RotationYawPitchRoll(currentRotation.X, currentRotation.Y, currentRotation.Z), Matrix.LookAtRH(currentPosition, New Vector3(0.0F, 0.0F, 0.0F), New Vector3(0.0F, 0.0F, 1.0F)))
            'Return Matrix.LookAtRH(New Vector3(0.0F, 0.0F, 0.0F), currentPosition, New Vector3(0.0F, 0.0F, 1.0F))
        End Get
    End Property
    Public ReadOnly Property InterpolatedView() As Matrix
        Get
            Return Matrix.Multiply(Matrix.LookAtRH(currentPosition, Vector3.Add(currentPosition, currentRotation), New Vector3(0.0F, 0.0F, 1.0F)), Matrix.RotationYawPitchRoll(currentRotation.X, currentRotation.Y, currentRotation.Z))
            'Return Matrix.LookAtRH(currentPosition, currentRotation, New Vector3(0.0F, 0.0F, 1.0F))
        End Get
    End Property
    Public ReadOnly Property PosRot(ByVal Index As Integer) As Matrix
        Get
            Return Matrix.Multiply(Matrix.Scaling(0.01F, 0.01F, 0.01F), Matrix.Multiply(Matrix.RotationYawPitchRoll(Rotations(Index).Y, Rotations(Index).Z, Rotations(Index).X), Matrix.Translation(Positions(Index))))
            'Return Matrix.LookAtRH(currentPosition, currentRotation, New Vector3(0.0F, 0.0F, 1.0F))
        End Get
    End Property
    Public ReadOnly Property InterpolatedProjection() As Matrix
        Get
            'Return Matrix.PerspectiveFovRH(Microsoft.DirectX.Direct3D.Geometry.DegreeToRadian(70), xDevice.PresentationParameters.BackBufferWidth / xDevice.PresentationParameters.BackBufferHeight, 0.1F, 1000.0F)
        End Get
    End Property
#End Region
End Class
